package org.example;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

/**
 * 音频下载器
 * 用于下载音频文件并保存为MP3格式
 */
public class AudioDownloader {
    private static final Logger logger = LoggerFactory.getLogger(AudioDownloader.class);
    
    /**
     * 下载音频文件
     * @param audioUrl 音频URL
     * @param outputPath 输出文件路径
     * @param fileName 文件名（不包含扩展名）
     * @return 下载的文件路径
     * @throws IOException 下载异常
     */
    public String downloadAudio(String audioUrl, String outputPath, String fileName) throws IOException {
        if (audioUrl == null || audioUrl.trim().isEmpty()) {
            throw new IllegalArgumentException("音频URL不能为空");
        }
        
        if (fileName == null || fileName.trim().isEmpty()) {
            throw new IllegalArgumentException("文件名不能为空");
        }
        
        // 创建输出目录
        Path outputDir = Paths.get(outputPath);
        if (!Files.exists(outputDir)) {
            Files.createDirectories(outputDir);
            logger.info("创建输出目录: {}", outputDir);
        }
        
        // 生成输出文件路径
        String outputFilePath = outputDir.resolve(fileName + ".mp3").toString();
        Path outputFile = Paths.get(outputFilePath);
        
        logger.info("开始下载音频: {}", audioUrl);
        logger.info("输出文件: {}", outputFilePath);
        
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(audioUrl);
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
            httpGet.setHeader("Referer", "https://www.bilibili.com");
            
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                HttpEntity entity = response.getEntity();
                
                if (entity == null) {
                    throw new IOException("响应实体为空");
                }
                
                // 获取文件大小用于进度显示
                long contentLength = entity.getContentLength();
                logger.info("文件大小: {} bytes", contentLength);
                
                // 下载文件
                try (InputStream inputStream = entity.getContent();
                     FileOutputStream outputStream = new FileOutputStream(outputFile.toFile())) {
                    
                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    long totalBytesRead = 0;
                    
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                        totalBytesRead += bytesRead;
                        
                        // 显示下载进度
                        if (contentLength > 0) {
                            int progress = (int) ((totalBytesRead * 100) / contentLength);
                            if (progress % 10 == 0) {
                                logger.info("下载进度: {}%", progress);
                            }
                        }
                    }
                }
            }
        }
        
        logger.info("音频下载完成: {}", outputFilePath);
        return outputFilePath;
    }
    
    /**
     * 下载音频文件（使用默认输出目录）
     * @param audioUrl 音频URL
     * @param fileName 文件名（不包含扩展名）
     * @return 下载的文件路径
     * @throws IOException 下载异常
     */
    public String downloadAudio(String audioUrl, String fileName) throws IOException {
        return downloadAudio(audioUrl, "downloads", fileName);
    }
    
    /**
     * 验证下载的文件
     * @param filePath 文件路径
     * @return 文件是否有效
     */
    public boolean validateDownloadedFile(String filePath) {
        Path path = Paths.get(filePath);
        
        if (!Files.exists(path)) {
            logger.error("文件不存在: {}", filePath);
            return false;
        }
        
        try {
            long fileSize = Files.size(path);
            if (fileSize == 0) {
                logger.error("文件大小为0: {}", filePath);
                return false;
            }
            
            logger.info("文件验证成功: {} (大小: {} bytes)", filePath, fileSize);
            return true;
            
        } catch (IOException e) {
            logger.error("验证文件时发生错误: {}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 清理临时文件
     * @param filePath 文件路径
     */
    public void cleanupFile(String filePath) {
        try {
            Path path = Paths.get(filePath);
            if (Files.exists(path)) {
                Files.delete(path);
                logger.info("已删除文件: {}", filePath);
            }
        } catch (IOException e) {
            logger.error("删除文件时发生错误: {}", e.getMessage());
        }
    }
    
    /**
     * 格式化文件大小
     * @param bytes 字节数
     * @return 格式化的文件大小字符串
     */
    public String formatFileSize(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return String.format("%.2f KB", bytes / 1024.0);
        } else if (bytes < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", bytes / (1024.0 * 1024.0));
        } else {
            return String.format("%.2f GB", bytes / (1024.0 * 1024.0 * 1024.0));
        }
    }
} 